﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace Warhammer40K_Simulator.view
{
    /// <summary>
    /// Interaction logic for browser.xaml
    /// </summary>
    public partial class browser : UserControl
    {
        public class OnarmySelectionChangedEvent : EventArgs
        {
            public model.army Army { get; set; }
            public OnarmySelectionChangedEvent(model.army army)
            {
                Army = army;
            }
        };

        public delegate void OnarmySelectionChangedDelegate(object sender, OnarmySelectionChangedEvent e);
        public event OnarmySelectionChangedDelegate OnarmySelectionChanged;

        public class OnUnitSelectionChangedEvent : EventArgs
        {
            public model.unit Unit { get; set; }
            public OnUnitSelectionChangedEvent(model.unit unit)
            {
                Unit = unit;
            }
        };

        public delegate void OnUnitSelectionChangedDelegate(object sender, OnUnitSelectionChangedEvent e);
        public event OnUnitSelectionChangedDelegate OnUnitSelectionChanged;

        public class OnFigureSelectionChangedEvent : EventArgs
        {
            public model.figure Figure { get; set; }
            public OnFigureSelectionChangedEvent(model.figure figure)
            {
                Figure = figure;
            }
        };

        public delegate void OnFigureSelectionChangedDelegate(object sender, OnFigureSelectionChangedEvent e);
        public event OnFigureSelectionChangedDelegate OnFigureSelectionChanged;



        public browser()
        {
            InitializeComponent();
            
            OnUnitSelectionChanged += new OnUnitSelectionChangedDelegate(browser_OnUnitSelectionChanged);
        }

        public void browser_OnUnitSelectionChanged(object sender, browser.OnUnitSelectionChangedEvent e)
        {
            if (sender != this && e.Unit != null)
            {
                TreeViewItem item = TreeView_Control.SelectedItem as TreeViewItem;
                if (item != null)
                {
                    item.IsSelected = false;
                }
            }        
        }
                
        public static readonly DependencyProperty modelproperty = DependencyProperty.Register("model"
            , typeof(model.model)
            , typeof(view.browser)
            , new PropertyMetadata(model_PropertyChanged));

        public model.model Model
        {
            get { return (model.model)GetValue(modelproperty); }
            set { SetValue(modelproperty, value); }
        }

        public static TreeViewItem FindTreeViewItemByName(String in_Name, ItemCollection items)
        {
            for (int i = 0; i < items.Count; i++)
            {
                TreeViewItem t = items[i] as TreeViewItem;
                if (t.Name == in_Name)
                {
                    return t;
                }
            }
            return null;
        }

        public static String strip_characters(String str, IEnumerable<char> toExclude)
        {
            StringBuilder sb = new StringBuilder();
            if (str != null)
            {
                for (int i = 0; i < str.Length; i++)
                {
                    char c = str[i];
                    if (!toExclude.Contains(c))
                        sb.Append(c);
                }
            }
            return sb.ToString();
        } 

        public void build_army_tree(ObservableCollection<model.army> armies, ItemCollection items)
        {
            Dictionary<TreeViewItem, bool> valid = new Dictionary<TreeViewItem, bool>();

            foreach (model.army n in armies)
            {
                TreeViewItem item = FindTreeViewItemByName(n.Name, items);
                if (item == null)
                {
                    StringBuilder s = new StringBuilder();
                    item = new TreeViewItem();
                    item.Name = strip_characters(n.Name, new HashSet<char>(new[] { ' ', '\t', '\n', '\r' }));
                    item.Header = n.Name;
                    item.Tag = n;
                    items.Add(item);
                    n.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(army_units_changed);
                }
                valid.Add(item, true);
                build_units_tree(n.Units, item.Items);
            }

            for (int i = items.Count - 1; i >= 0; i--)
            {
                TreeViewItem item = items[i] as TreeViewItem;
                if (!valid.ContainsKey(item))
                {
                    items.RemoveAt(i);
                }
            }
        }

        public void build_units_tree(ObservableCollection<model.unit> units, ItemCollection items)
        {
            Dictionary<TreeViewItem, bool> valid = new Dictionary<TreeViewItem, bool>();

            foreach (model.unit u in units)
            {
                TreeViewItem item = FindTreeViewItemByName(u.Name, items);
                if (item == null)
                {
                    item = new TreeViewItem();
                    item.Name = strip_characters(u.Name, new HashSet<char>(new[] { ' ', '\t', '\n', '\r' }));
                    item.Header = u.Name;
                    item.Tag = u;
                    items.Add(item);
                    u.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(units_figure_changed);
                }
                valid.Add(item, true);
                build_figures_tree(u.Figures, item.Items);
            }

            for (int i = items.Count - 1; i >= 0; i--)
            {
                TreeViewItem item = items[i] as TreeViewItem;
                if (!valid.ContainsKey(item))
                {
                    items.RemoveAt(i);
                }
            }
        }

        public void build_figures_tree(ObservableCollection<model.figure> figures, ItemCollection items)
        {
            Dictionary<TreeViewItem, bool> valid = new Dictionary<TreeViewItem, bool>();

            foreach (model.figure f in figures)
            {
                TreeViewItem item = FindTreeViewItemByName(f.Name, items);
                if (item == null)
                {
                    item = new TreeViewItem();
                    item.Name = strip_characters(f.Name, new HashSet<char>(new[] { ' ', '\t', '\n', '\r' }));
                    item.Header = f.Name;
                    item.Tag = f;
                    items.Add(item);
                }
                valid.Add(item, true);
            }

            for (int i = items.Count - 1; i >= 0; i--)
            {
                TreeViewItem item = items[i] as TreeViewItem;
                if (!valid.ContainsKey(item))
                {
                    items.RemoveAt(i);
                }
            }
        }

        protected static void model_PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            browser b = (browser)obj;
            b.Model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(b.model_codices_changed);
            b.TextBox_ModelName.Text = b.Model.Name;
            b.MenuItem_AddToArmy1.Visibility = b.Model.ReadOnly ? Visibility.Visible : Visibility.Collapsed;
            b.MenuItem_AddToArmy2.Visibility = b.Model.ReadOnly ? Visibility.Visible : Visibility.Collapsed;
            b.MenuItem_Delete.Visibility = b.Model.ReadOnly ? Visibility.Collapsed : Visibility.Visible;
            b.build_army_tree(b.Model.Armies, b.TreeView_Control.Items);
        }

        void model_codices_changed(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            model.model m = sender as model.model;
            build_army_tree(m.Armies, TreeView_Control.Items);
        }  

        void army_units_changed(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            model.army a = sender as model.army;
            TreeViewItem armies = TreeView_Control.Items[0] as TreeViewItem;
            if (armies != null)
            {
                armies.IsExpanded = true;
                build_units_tree(a.Units, armies.Items);
            }
        }

        void units_figure_changed(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            model.army c = sender as model.army;
            // rebuild_army_tree(m.Armies, TreeView_Control.Items);
        }

        private void TreeView_Control_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            TreeViewItem t = e.NewValue as TreeViewItem;
            if (t != null)
            {
                if (t.Tag != null)
                {
                    model.army c = t.Tag as model.army;
                    if (c != null)
                    {                      
                        if (OnarmySelectionChanged != null)
                        {
                            OnarmySelectionChanged(sender, new OnarmySelectionChangedEvent(c));
                        }  
                    }

                    model.unit u = t.Tag as model.unit;
                    if (u != null)
                    {
                        MenuItem_AddToArmy1.IsEnabled = true;
                        MenuItem_AddToArmy2.IsEnabled = true;
                        MenuItem_Delete.IsEnabled = true;

                        if (OnUnitSelectionChanged != null)
                        {
                            OnUnitSelectionChanged(this, new OnUnitSelectionChangedEvent(u));
                        }
                    }
                    else
                    {
                        MenuItem_AddToArmy1.IsEnabled = false;
                        MenuItem_AddToArmy2.IsEnabled = false;
                        MenuItem_Delete.IsEnabled = false;
                    }

                    model.figure f = t.Tag as model.figure;
                    if (f != null)
                    {
                        if (OnFigureSelectionChanged != null)
                        {
                            OnFigureSelectionChanged(sender, new OnFigureSelectionChangedEvent(f));
                        }
                    }
                }
            }
        }

        private void MenuItem_AddToArmy1_Click(object sender, RoutedEventArgs e)
        {
            model.model m = FindResource("army1") as model.model;
            if (m != null)
            {
                TreeViewItem t = TreeView_Control.SelectedItem as TreeViewItem;
                if (t != null)
                {
                    model.unit u = t.Tag as model.unit;
                    if (u != null)
                    {
                        ObservableCollection<model.unit> units = new ObservableCollection<model.unit>(m.Armies[0].Units);
                        model.unit newunit = u.clone();
                        units.Add(newunit);
                        m.Armies[0].Units = units;
                    }
                }
            }           
        }

        private void MenuItem_AddToArmy2_Click(object sender, RoutedEventArgs e)
        {

        }

        private void MenuItem_Delete_Click(object sender, RoutedEventArgs e)
        {

        }
    }
}
